home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cdrtools-1.10 / libfile / softmagic.c < prev   
Encoding:
C/C++ Source or Header  |  2000-03-06  |  8.4 KB  |  368 lines

  1. /*
  2. **    find file types by using a modified "magic" file
  3. **
  4. **    based on file v3.22 by Ian F. Darwin (see below)
  5. **
  6. **    Modified for mkhybrid James Pearson 19/5/98
  7. */
  8.  
  9. /*
  10.  * softmagic - interpret variable magic from /etc/magic
  11.  *
  12.  * Copyright (c) Ian F. Darwin, 1987.
  13.  * Written by Ian F. Darwin.
  14.  *
  15.  * This software is not subject to any license of the American Telephone
  16.  * and Telegraph Company or of the Regents of the University of California.
  17.  *
  18.  * Permission is granted to anyone to use this software for any purpose on
  19.  * any computer system, and to alter it and redistribute it freely, subject
  20.  * to the following restrictions:
  21.  *
  22.  * 1. The author is not responsible for the consequences of use of this
  23.  *    software, no matter how awful, even if they arise from flaws in it.
  24.  *
  25.  * 2. The origin of this software must not be misrepresented, either by
  26.  *    explicit claim or by omission.  Since few users ever read sources,
  27.  *    credits must appear in the documentation.
  28.  *
  29.  * 3. Altered versions must be plainly marked as such, and must not be
  30.  *    misrepresented as being the original software.  Since few users
  31.  *    ever read sources, credits must appear in the documentation.
  32.  *
  33.  * 4. This notice may not be removed or altered.
  34.  */
  35.  
  36. #include <stdio.h>
  37. #include <string.h>
  38. #include <stdlib.h>
  39. #include <time.h>
  40. #include <sys/types.h>
  41.  
  42. #include "file.h"
  43.  
  44. #ifndef    lint
  45. static char *moduleid = 
  46.     "@(#)$Id: softmagic.c,v 1.34 1997/01/15 19:28:35 christos Exp $";
  47. #endif    /* lint */
  48.  
  49. /* static int match    __P((unsigned char *, int)); */
  50. static char *match    __P((unsigned char *, int));
  51. static int mget        __P((union VALUETYPE *,
  52.                  unsigned char *, struct magic *, int));
  53. static int mcheck    __P((union VALUETYPE *, struct magic *));
  54. #ifdef    __used__
  55. static void mdebug    __P((int32, char *, int));
  56. #endif
  57. static int mconvert    __P((union VALUETYPE *, struct magic *));
  58.  
  59. /*
  60.  * softmagic - lookup one file in database 
  61.  * (already read from /etc/magic by apprentice.c).
  62.  * Passed the name and FILE * of one file to be typed.
  63.  */
  64. /*ARGSUSED1*/        /* nbytes passed for regularity, maybe need later */
  65. char *
  66. softmagic(buf, nbytes)
  67. unsigned char *buf;
  68. int nbytes;
  69. {
  70.     return (match(buf, nbytes));
  71. }
  72.  
  73. /*
  74.  * Go through the whole list, stopping if you find a match.  Process all
  75.  * the continuations of that match before returning.
  76.  *
  77.  * We support multi-level continuations:
  78.  *
  79.  *    At any time when processing a successful top-level match, there is a
  80.  *    current continuation level; it represents the level of the last
  81.  *    successfully matched continuation.
  82.  *
  83.  *    Continuations above that level are skipped as, if we see one, it
  84.  *    means that the continuation that controls them - i.e, the
  85.  *    lower-level continuation preceding them - failed to match.
  86.  *
  87.  *    Continuations below that level are processed as, if we see one,
  88.  *    it means we've finished processing or skipping higher-level
  89.  *    continuations under the control of a successful or unsuccessful
  90.  *    lower-level continuation, and are now seeing the next lower-level
  91.  *    continuation and should process it.  The current continuation
  92.  *    level reverts to the level of the one we're seeing.
  93.  *
  94.  *    Continuations at the current level are processed as, if we see
  95.  *    one, there's no lower-level continuation that may have failed.
  96.  *
  97.  *    If a continuation matches, we bump the current continuation level
  98.  *    so that higher-level continuations are processed.
  99.  */
  100. static char *
  101. match(s, nbytes)
  102. unsigned char    *s;
  103. int nbytes;
  104. {
  105.     int magindex = 0;
  106.     union VALUETYPE p;
  107.  
  108.     for (magindex = 0; magindex < nmagic; magindex++) {
  109.         /* if main entry matches, print it... */
  110.         if (!mget(&p, s, &magic[magindex], nbytes) ||
  111.             !mcheck(&p, &magic[magindex])) {
  112.                 /* 
  113.                  * main entry didn't match,
  114.                  * flush its continuations
  115.                  */
  116.                 while (magindex < nmagic &&
  117.                        magic[magindex + 1].cont_level != 0)
  118.                        magindex++;
  119.                 continue;
  120.         }
  121.  
  122.         return (magic[magindex].desc);
  123.     }
  124.     return 0;            /* no match at all */
  125. }
  126.  
  127.  
  128. /*
  129.  * Convert the byte order of the data we are looking at
  130.  */
  131. static int
  132. mconvert(p, m)
  133. union VALUETYPE *p;
  134. struct magic *m;
  135. {
  136.     switch (m->type) {
  137.     case BYTE:
  138.     case SHORT:
  139.     case LONG:
  140.     case DATE:
  141.         return 1;
  142.     case STRING:
  143.         {
  144.             char *ptr;
  145.  
  146.             /* Null terminate and eat the return */
  147.             p->s[sizeof(p->s) - 1] = '\0';
  148.             if ((ptr = strchr(p->s, '\n')) != NULL)
  149.                 *ptr = '\0';
  150.             return 1;
  151.         }
  152.     case BESHORT:
  153.         p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
  154.         return 1;
  155.     case BELONG:
  156.     case BEDATE:
  157.         p->l = (int32)
  158.             ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
  159.         return 1;
  160.     case LESHORT:
  161.         p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
  162.         return 1;
  163.     case LELONG:
  164.     case LEDATE:
  165.         p->l = (int32)
  166.             ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
  167.         return 1;
  168.     default:
  169.         return 0;
  170.     }
  171. }
  172.  
  173. #ifdef    __used__
  174. static void
  175. mdebug(offset, str, len)
  176. int32 offset;
  177. char *str;
  178. int len;
  179. {
  180.     (void) fprintf(stderr, "mget @%d: ", offset);
  181.     showstr(stderr, (char *) str, len);
  182.     (void) fputc('\n', stderr);
  183.     (void) fputc('\n', stderr);
  184. }
  185. #endif
  186.  
  187. static int
  188. mget(p, s, m, nbytes)
  189. union VALUETYPE* p;
  190. unsigned char    *s;
  191. struct magic *m;
  192. int nbytes;
  193. {
  194.     int32 offset = m->offset;
  195.  
  196.     if (offset + sizeof(union VALUETYPE) <= nbytes)
  197.         memcpy(p, s + offset, sizeof(union VALUETYPE));
  198.     else {
  199.         /*
  200.          * the usefulness of padding with zeroes eludes me, it
  201.          * might even cause problems
  202.          */
  203.         int32 have = nbytes - offset;
  204.         memset(p, 0, sizeof(union VALUETYPE));
  205.         if (have > 0)
  206.             memcpy(p, s + offset, have);
  207.     }
  208.  
  209.     if (!mconvert(p, m))
  210.         return 0;
  211.  
  212.     if (m->flag & INDIR) {
  213.  
  214.         switch (m->in.type) {
  215.         case BYTE:
  216.             offset = p->b + m->in.offset;
  217.             break;
  218.         case SHORT:
  219.             offset = p->h + m->in.offset;
  220.             break;
  221.         case LONG:
  222.             offset = p->l + m->in.offset;
  223.             break;
  224.         }
  225.  
  226.         if (offset + sizeof(union VALUETYPE) > nbytes)
  227.             return 0;
  228.  
  229.         memcpy(p, s + offset, sizeof(union VALUETYPE));
  230.  
  231.         if (!mconvert(p, m))
  232.             return 0;
  233.     }
  234.     return 1;
  235. }
  236.  
  237. static int
  238. mcheck(p, m)
  239. union VALUETYPE* p;
  240. struct magic *m;
  241. {
  242.     register uint32 l = m->value.l;
  243.     register uint32 v;
  244.     int matched;
  245.  
  246.     if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) {
  247.         fprintf(stderr, "BOINK");
  248.         return 1;
  249.     }
  250.  
  251.  
  252.     switch (m->type) {
  253.     case BYTE:
  254.         v = p->b;
  255.         break;
  256.  
  257.     case SHORT:
  258.     case BESHORT:
  259.     case LESHORT:
  260.         v = p->h;
  261.         break;
  262.  
  263.     case LONG:
  264.     case BELONG:
  265.     case LELONG:
  266.     case DATE:
  267.     case BEDATE:
  268.     case LEDATE:
  269.         v = p->l;
  270.         break;
  271.  
  272.     case STRING:
  273.         l = 0;
  274.         /* What we want here is:
  275.          * v = strncmp(m->value.s, p->s, m->vallen);
  276.          * but ignoring any nulls.  bcmp doesn't give -/+/0
  277.          * and isn't universally available anyway.
  278.          */
  279.         v = 0;
  280.         {
  281.             register unsigned char *a = (unsigned char*)m->value.s;
  282.             register unsigned char *b = (unsigned char*)p->s;
  283.             register int len = m->vallen;
  284.  
  285.             while (--len >= 0)
  286.                 if ((v = *b++ - *a++) != '\0')
  287.                     break;
  288.         }
  289.         break;
  290.     default:
  291.         return 0;/*NOTREACHED*/
  292.     }
  293.  
  294.     v = signextend(m, v) & m->mask;
  295.  
  296.     switch (m->reln) {
  297.     case 'x':
  298.         if (debug)
  299.             (void) fprintf(stderr, "%u == *any* = 1\n", v);
  300.         matched = 1;
  301.         break;
  302.  
  303.     case '!':
  304.         matched = v != l;
  305.         if (debug)
  306.             (void) fprintf(stderr, "%u != %u = %d\n",
  307.                        v, l, matched);
  308.         break;
  309.  
  310.     case '=':
  311.         matched = v == l;
  312.         if (debug)
  313.             (void) fprintf(stderr, "%u == %u = %d\n",
  314.                        v, l, matched);
  315.         break;
  316.  
  317.     case '>':
  318.         if (m->flag & UNSIGNED) {
  319.             matched = v > l;
  320.             if (debug)
  321.                 (void) fprintf(stderr, "%u > %u = %d\n",
  322.                            v, l, matched);
  323.         }
  324.         else {
  325.             matched = (int32) v > (int32) l;
  326.             if (debug)
  327.                 (void) fprintf(stderr, "%d > %d = %d\n",
  328.                            v, l, matched);
  329.         }
  330.         break;
  331.  
  332.     case '<':
  333.         if (m->flag & UNSIGNED) {
  334.             matched = v < l;
  335.             if (debug)
  336.                 (void) fprintf(stderr, "%u < %u = %d\n",
  337.                            v, l, matched);
  338.         }
  339.         else {
  340.             matched = (int32) v < (int32) l;
  341.             if (debug)
  342.                 (void) fprintf(stderr, "%d < %d = %d\n",
  343.                            v, l, matched);
  344.         }
  345.         break;
  346.  
  347.     case '&':
  348.         matched = (v & l) == l;
  349.         if (debug)
  350.             (void) fprintf(stderr, "((%x & %x) == %x) = %d\n",
  351.                        v, l, l, matched);
  352.         break;
  353.  
  354.     case '^':
  355.         matched = (v & l) != l;
  356.         if (debug)
  357.             (void) fprintf(stderr, "((%x & %x) != %x) = %d\n",
  358.                        v, l, l, matched);
  359.         break;
  360.  
  361.     default:
  362.         matched = 0;
  363.         break;/*NOTREACHED*/
  364.     }
  365.  
  366.     return matched;
  367. }
  368.